/**
 * @fileoverview
 * This script defines a widget for interacting with image data from FlyTED.
 * @requires flyui.util
 * @requires flyui.sparql.Service
 * @requires flyui.flyted.Service
 * @requires YAHOO.util.Connect
 * @requires jQuery
 * For license terms see http://flyui.googlecode.com
 */
 
flyui.namespace("flyui.flyted");
 
 

/*
 * ----------------------------------------------------------------
 *                             WIDGET
 * ----------------------------------------------------------------
 */







flyui.flyted.BatchWidget = function( service, renderer ) {
    var _context = "flyui.flyted.BatchWidget";
    try {
        
        flyui.debug("call private constructor", _context);
        this.__init__(service, renderer);
        
    } catch (unexpected) {
        flyui.debug("rethrowing "+unexpected.name+", "+unexpected.message, _context);
        throw unexpected;    
    }
    
}



 
 



/** @private */
flyui.flyted.BatchWidget.prototype._controller = null;

/**
 * @private
 * @type flyui.mvcutils.GenericModel2
 */ 
flyui.flyted.BatchWidget.prototype._model = null;

/**
 * @private
 */
flyui.flyted.BatchWidget.prototype._renderer = null;

/**
 * @private
 */
flyui.flyted.BatchWidget.prototype._service = null;










/**
 * @private
 */
flyui.flyted.BatchWidget.prototype.__init__ = function( service, renderer ) {
    var _context = "flyui.flyted.BatchWidget.prototype.__init__";
    try {
        
        this._service = service;
        this._renderer = renderer;
        
        flyui.debug("create a model", _context);
        this._model = new flyui.mvcutils.GenericModel2();
        this._model.setDefinition(flyui.flyted.BatchWidget.modelDefinition);
        
        flyui.debug("create a controller", _context);
        this._controller = new flyui.flyted.BatchWidget.Controller(this._model, service, this);
        
        flyui.debug("connect the renderer to the model", _context);
        this._renderer.connect(this._model);
        
    } catch (unexpected) {
        flyui.debug("rethrowing "+unexpected.name+", "+unexpected.message, _context);
        throw unexpected;    
    }
};







/**
 * @public
 * @param {Array<String>} querynames
 * @param {Array<flyui.flybase.Gene>} genes
 */
flyui.flyted.BatchWidget.prototype.findImagesByGeneBatch = function( querynames, genes ) {
    var _context = "flyui.flyted.BatchWidget.prototype.findGenesByAnyNameBatch";
    try {
        
        flyui.debug("pass ["+querynames+"], ["+genes+"] through to controller", _context);
        this._controller.findImagesByGeneBatch(querynames, genes);
        
    } catch (unexpected) {
        flyui.debug("rethrowing "+unexpected.name+", "+unexpected.message, _context);
        throw unexpected;    
    }
};







/*
 * ----------------------------------------------------------------
 *                             CONTROLLER
 * ----------------------------------------------------------------
 */






/**
 * @class
 */
flyui.flyted.BatchWidget.Controller = function( model, service, controllee ) {
    var _context = "flyui.flyted.BatchWidget.Controller";
    try {
        
        this._model = null;
        this._service = null;
        this._controllee = null;
        
        flyui.debug("call private constructor", _context);
        this.__init__(model, service, controllee);        
        
    } catch (unexpected) {
        flyui.debug("rethrowing "+unexpected.name+", "+unexpected.message, _context);
        throw unexpected;    
    }
};








/**
 * @private
 */
flyui.flyted.BatchWidget.Controller.prototype.__init__ = function( model, service, controllee ) {
    var _context = "flyui.flyted.BatchWidget.Controller.prototype.__init__";
    try {
        
        this._model = model;
        this._service = service;
        this._controllee = controllee;
        
    } catch (unexpected) {
        flyui.debug("rethrowing "+unexpected.name+", "+unexpected.message, _context);
        throw unexpected;    
    }
};








/**
 * @public
 */
flyui.flyted.BatchWidget.Controller.prototype.findImagesByGeneBatch = function( querynames, genes ) {
    var _context = "flyui.flyted.BatchWidget.Controller.prototype.findGenesByAnyNameBatch";
    try {
        
        flyui.info("findImagesByGeneBatch: "+querynames+" || "+genes, _context);
        flyui.debug("pass through to private implementation", _context);
        this._findImagesByGeneBatch(querynames, genes, this._findImagesByGeneBatchSuccess(), this._findImagesByGeneBatchFailure());
        
    } catch (unexpected) {
        flyui.debug("rethrowing "+unexpected.name+", "+unexpected.message, _context);
        throw unexpected;    
    }
};








/**
 * @private
 */
flyui.flyted.BatchWidget.Controller.prototype._findImagesByGeneBatch = function( querynames, genes, success, failure ) {
    var _context = "flyui.flyted.BatchWidget.Controller.prototype._findImagesByGeneBatch";
    try {
        
        flyui.debug("querynames: "+querynames, _context);
        flyui.debug("genes: "+genes, _context);
        
        flyui.debug("set state pending", _context);
        this._model.set("STATE", "PENDING");
        
        flyui.debug("set model property query", _context);
        this._model.set("QUERY", [querynames, genes]);

        flyui.debug("set result null", _context);
        this._model.set("RESULTS", null);
                
        flyui.debug("set message null", _context);
        this._model.set("MESSAGE", null);
                
        var flybaseids = [];
        for (var i=0;i<genes.length;i++) {
            flybaseids[i] = genes[i].flybaseID;
        }
        flyui.debug("kick off request: "+flybaseids, _context);
        this._service.findImagesByFlybaseGeneIDBatch(flybaseids, success, failure);        
        
    } catch (unexpected) {
        flyui.debug("rethrowing "+unexpected.name+", "+unexpected.message, _context);
        throw unexpected;    
    }
};









/**
 * @private
 */
flyui.flyted.BatchWidget.Controller.prototype._findImagesByGeneBatchSuccess = function() {
    var _context = "flyui.flyted.BatchWidget.Controller.prototype._findImagesByGeneBatchSuccess";
    var self = this;
    /**
     */
    return function( results ) {
        try {
            
            flyui.info("request success", _context);
            
            flyui.debug("set model results", _context);
            self._model.set("RESULTS", results);
            
            flyui.debug("set model state", _context);
            self._model.set("STATE", "READY");
            
            var explanation = "Images depict expression patterns of genes involved in spermatogenesis in the testis of Drosophila melanogaster. Empty table cells indicate that no images are available from FlyTED for that gene.";
            self._model.set("MESSAGE", explanation);
            
        } catch (unexpected) {
            flyui.debug("rethrowing "+unexpected.name+", "+unexpected.message, _context);
            throw unexpected;    
        }
    };
};







/**
 * @private
 */
flyui.flyted.BatchWidget.Controller.prototype._findImagesByGeneBatchFailure = function() {
    var _context = "flyui.flyted.BatchWidget.Controller.prototype._findImagesByGeneBatchFailure";
    var self = this;
    /**
     * @param {ResponseObject} response
     */
    return function( response ) {
        try {
            
            flyui.err("request failed: "+response.status+" "+response.statusText, _context);
            self._model.set("MESSAGE", "there was an error retrieving data from the server, see the logs for more info");
            self._model.set("STATE", "SERVERERROR");
            
        } catch (unexpected) {
            flyui.debug("rethrowing "+unexpected.name+", "+unexpected.message, _context);
            throw unexpected;    
        }
    };
};







/*
 * ----------------------------------------------------------------
 *                             MODEL DEFINITION
 * ----------------------------------------------------------------
 */





/** 
 * @type Object
 */
flyui.flyted.BatchWidget.modelDefinition = {

    properties : [ "STATE", "RESULTS", "MESSAGE", "QUERY" ],
    
    values : {
        "STATE" : [ "READY", "PENDING", "SERVERERROR", "UNEXPECTEDERROR" ]
    },
    
    initialize : function( data ) {
        data["STATE"] = "READY";
        data["RESULTS"] = null;
        data["MESSAGE"] = null;
        data["QUERY"] = null;
    }

};







/*
 * ----------------------------------------------------------------
 *                             DEFAULT RENDERER
 * ----------------------------------------------------------------
 */







flyui.flyted.BatchWidget.DefaultRenderer = function() {};


/** 
 * @private 
 * @type Element
 */
flyui.flyted.BatchWidget.DefaultRenderer.prototype._canvas = null;

/**
 * @private 
 * @type Element
 */
flyui.flyted.BatchWidget.DefaultRenderer.prototype._pendingPane = null;

/**
 * @private 
 * @type Element
 */
flyui.flyted.BatchWidget.DefaultRenderer.prototype._resultsSummaryPane = null;

/**
 * @private 
 * @type Element
 */
flyui.flyted.BatchWidget.DefaultRenderer.prototype._resultsPane = null;

/**
 * @private 
 * @type Element
 */
flyui.flyted.BatchWidget.DefaultRenderer.prototype._messagePane = null;





/**
 * Set the DOM element to which this renderer applies and initialise it.
 * @param {Element} canvas
 */
flyui.flyted.BatchWidget.DefaultRenderer.prototype.setCanvas = function( canvas ) {
    var _context = "flyui.flyted.BatchWidget.DefaultRenderer.prototype.setCanvas";
    try {
        
        flyui.debug("set canvas", _context);
        this._canvas = $(canvas);
        this._initCanvas();
        
        
    } catch (unexpected) {
        flyui.debug("rethrowing "+unexpected.name+", "+unexpected.message, _context);
        throw unexpected;    
    }
};






/**
 * @private
 * @param {Element} canvas
 */
flyui.flyted.BatchWidget.DefaultRenderer.prototype._initCanvas = function() {
    var _context = "flyui.flyted.BatchWidget.DefaultRenderer.prototype._initCanvas";
    try {
        
        flyui.debug("begin init canvas", _context);
        
        var canvas = this._canvas;
        canvas.addClass("batchFlytedImageWidget");

        var pp = $("<p class='pendingPane'>pending (please wait, this can take up to 10 seconds) ...</p>").hide();
        canvas.append(pp);
        this._pendingPane = pp;

        var rsp = $("<p class='resultsSummaryPane'>this text should never be displayed</p>").hide();
        canvas.append(rsp);
        this._resultsSummaryPane = rsp;
        
        var rp = $("<div class='resultsPane'></div>").hide();
        canvas.append(rp);
        this._resultsPane = rp;
        
        var mp = $("<p class='messagePane'>this text should never be displayed</p>").hide();
        canvas.append(mp);
        this._messagePane = mp;            

        flyui.debug("init canvas done", _context);
        
    } catch (unexpected) {
        flyui.debug("rethrowing "+unexpected.name+", "+unexpected.message, _context);
        throw unexpected;    
    }
};





/**
 * @public
 */
flyui.flyted.BatchWidget.DefaultRenderer.prototype.connect = function( model ) {
    var _context = "flyui.flyted.BatchWidget.DefaultRenderer.prototype.connect";
    try {
        
        flyui.debug("connect to model", _context);
        model.subscribeAll(this._onModelChanged, this);
        
    } catch (unexpected) {
        flyui.debug("rethrowing "+unexpected.name+", "+unexpected.message, _context);
        throw unexpected;    
    }
};





/**
 * @private
 */
flyui.flyted.BatchWidget.DefaultRenderer.prototype._onModelChanged = function( type, args, self ) {
    var _context = "flyui.flyted.BatchWidget.DefaultRenderer.prototype._onModelChanged";
    try {
        
        var handlers = {
            "STATE":"_onStateChanged",
            "QUERY":"_onQueryChanged",
            "RESULTS":"_onResultsChanged",
            "MESSAGE":"_onMessageChanged"
        };
        var handler = handlers[type];
        flyui.debug("call model changed handler: "+handler, _context);
        self[handler](args[0], args[1], args[2]);
        
    } catch (unexpected) {
        flyui.debug("rethrowing "+unexpected.name+", "+unexpected.message, _context);
        throw unexpected;    
    }
};






/**
 * @private
 */
flyui.flyted.BatchWidget.DefaultRenderer.prototype._onQueryChanged = function( from, to, get ) {
    var _context = "flyui.flyted.BatchWidget.DefaultRenderer.prototype._onQueryChanged";
    try {
        
        // do nothing, we will access the value later
        flyui.debug("query changed from "+from+" to "+to, _context);
        
    } catch (unexpected) {
        flyui.debug("rethrowing "+unexpected.name+", "+unexpected.message, _context);
        throw unexpected;    
    }
};






/**
 * @private
 */
flyui.flyted.BatchWidget.DefaultRenderer.prototype._onStateChanged = function( from, to, get ) {
    var _context = "flyui.flyted.BatchWidget.DefaultRenderer.prototype._onStateChanged";
    try {
        
        flyui.debug("state changed from "+from+" to "+to, _context);

        if ( to == "PENDING" ) {
            this._pendingPane.show();
            this._messagePane.hide();
            this._resultsSummaryPane.hide();
            this._resultsPane.hide();
        }
        else if ( to == "READY" ) {
            this._pendingPane.hide();
            this._messagePane.show();
            this._resultsSummaryPane.show();
            this._resultsPane.show();         
        } 
        else if ( to == "SERVERERROR" || to == "UNEXPECTEDERROR" ) {
            this._pendingPane.hide();
            this._messagePane.show();
            this._resultsSummaryPane.hide();
            this._resultsPane.hide();         
        } 
        else {
            // this should never happen
            throw {message:"invalid state: "+to};
        }
        
    } catch (unexpected) {
        flyui.debug("rethrowing "+unexpected.name+", "+unexpected.message, _context);
        throw unexpected;    
    }
};






/**
 * @private
 */
flyui.flyted.BatchWidget.DefaultRenderer.prototype._onResultsChanged = function( from, to, get ) {
    var _context = "flyui.flyted.BatchWidget.DefaultRenderer.prototype._onResultsChanged";
    try {
        
        flyui.debug("results changed to: "+to, _context);
        
        if (to == null) {
            flyui.debug("empty results summary pane", _context);
            this._resultsSummaryPane.empty();
            flyui.debug("empty results pane", _context);
            this._resultsPane.empty();
        } 
        
        else {

            var query = get("QUERY");
            
            flyui.debug("render results summary", _context);
            this._renderResultsSummary(query, to);
    
            flyui.debug("render results", _context);
            this._renderResults(query, to);        
            
        }
        
    } catch (unexpected) {
        flyui.debug("rethrowing "+unexpected.name+", "+unexpected.message, _context);
        throw unexpected;    
    }
};







/**
 * @private
 */
flyui.flyted.BatchWidget.DefaultRenderer.prototype._onMessageChanged = function( from, to, get ) {
    var _context = "flyui.flyted.BatchWidget.DefaultRenderer.prototype._onMessageChanged";
    try {
        
        flyui.debug("message changed to: "+to, _context);
        
        if (to == null) {
            flyui.debug("empty messsage pane", _context);
            this._messagePane.empty();
        } 
        
        else {

            this._messagePane.html(to);
            
        }
        
    } catch (unexpected) {
        flyui.debug("rethrowing "+unexpected.name+", "+unexpected.message, _context);
        throw unexpected;    
    }
};









/**
 * @private
 */
flyui.flyted.BatchWidget.DefaultRenderer.prototype._renderResultsSummary = function( query, results ) {
    var _context = "flyui.flyted.BatchWidget.DefaultRenderer.prototype._renderResultsSummary";
    try {
        
        flyui.debug("render results summary", _context);

        var querynames = query[0];
        var genes = query[1];
        
        var count = 0;
        
        for (genename in results) {
            flyui.debug("counting images for "+genename, _context);
            count += results[genename].images.length;               
        }
        
        var content = "found "+count+" images from <a href='http://www.fly-ted.org'>FlyTED</a> (data retrieved on 2008-12-03) ...";

        this._resultsSummaryPane.html(content);
        
    } catch (unexpected) {
        flyui.debug("rethrowing "+unexpected.name+", "+unexpected.message, _context);
        throw unexpected;    
    }
};








/**
 * @private
 */
flyui.flyted.BatchWidget.DefaultRenderer.prototype._renderResults = function( query, results ) {
    var _context = "flyui.flyted.BatchWidget.DefaultRenderer.prototype._renderResults";
    try {
        flyui.debug("render results", _context);

        // query has both anyNames + geneObjects
        
        // querynames: anyNames
        var querynames = query[0];
        // genes; gene objects
        var genes = query[1];
        
        var content = "<table>";

        content += "<thead><tr><th>gene</th><th>images</th></tr></thead><tbody>";
        
        for (var i=0; i<querynames.length; i++) {
            var n = querynames[i];
            var c = genes[i].annotationSymbols[0];
            var id = genes[i].flybaseID;

            content += "<tr><td>" + n + "</td><td>"; // use query name because that's what the user asked for

            // TODO add links to flyted gene report pages? or not?
                        
            flyui.debug("looking for results for gene "+id, _context);
            
            var fbgn = "http://openflydata.org/id/flybase/feature/" + id ;
            var imgs = results[fbgn].images;
            
            flyui.debug("found images "+imgs.length+" in result for gene "+id, _context);
            
//            content += imgs.length ;
            
            for (var image in imgs) {
            	flyui.debug("found image "+image+" in result for gene "+id, _context);
            	flyui.debug("found image "+imgs[image].flytedURL+" in result for gene "+id, _context);
            	content +=   "<div class=\"result\">";
	    		content +=          "<p><a href=\"" + imgs[image].flytedURL + "\">";
			    content +=              "<img src=\"" + imgs[image].thumbnailURL + "\" alt=\"flyted thumbnail image\">";
			    content +=          "</img></a></p>"; 
			    content +=          "<p class=\"caption\">"+imgs[image].caption+"</p>"
			    content +=      "</div>";
            }
            
            content += "</td></tr>";
        }

        content += "</tbody></table>";
        
        flyui.debug("results pane content: "+content, _context);
        this._resultsPane.html(content);
        
    } catch (unexpected) {
        flyui.debug("rethrowing "+unexpected.name+", "+unexpected.message, _context);
        throw unexpected;    
    }
};




























